package cz.muni.fi.pv112.cranesimulator.utils.handlers.opengl;

import com.jogamp.opengl.util.texture.Texture;
import cz.muni.fi.pv112.cranesimulator.models.Model;
import cz.muni.fi.pv112.cranesimulator.models.OBJModel;
import javax.media.opengl.GL2;
import static cz.muni.fi.pv112.cranesimulator.utils.handlers.opengl.DisplayListHandler.displayDisplayList;
import static cz.muni.fi.pv112.cranesimulator.utils.handlers.opengl.DisplayListHandler.displayDisplayLists;

/**
 *
 * @author Michal Ďuriš
 */
public class ModelDisplayHandler {

    public static void drawQuadsPolygonModel(GL2 gl, Model model,
                                             Texture texture,
                                             int textureWrapSValue,
                                             int textureWrapTValue) {
        drawQuadsPolygonModel(gl,
                model.getVertexCoords(), model.getNormalCoords(),
                model.getTextureCoords(),
                texture, textureWrapSValue, textureWrapTValue);
    }

    public static void drawQuadsPolygonModel(GL2 gl, Model model,
                                             Texture[] textures,
                                             int textureWrapSValue,
                                             int textureWrapTValue) {
        drawQuadsPolygonModel(gl,
                model.getVertexCoords(), model.getNormalCoords(),
                model.getTextureCoords(),
                textures, textureWrapSValue, textureWrapTValue);
    }

    private static void drawQuadsPolygonModel(GL2 gl,
                                              float[][] vertexCoords,
                                              float[][] normalCoords,
                                              float[][] textureCoords,
                                              Texture texture,
                                              int textureWrapSValue,
                                              int textureWrapTValue) {
        boolean texturingEnabled = false;
        boolean normalsEnabled = false;

        if (normalCoords != null) {
            normalsEnabled = true;
        }

        if (textureCoords != null) {
            texturingEnabled = true;

            gl.glEnable(GL2.GL_TEXTURE_2D);

            texture.bind(gl);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S,
                    textureWrapSValue);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T,
                    textureWrapTValue);
        }

        gl.glBegin(GL2.GL_QUADS);

        for (int i = 0; i < vertexCoords.length; i++) {
            if (normalsEnabled) {
                gl.glNormal3fv(normalCoords[i], 0);
            }

            if (texturingEnabled) {
                gl.glTexCoord2fv(textureCoords[i], 0);
            }

            gl.glVertex3fv(vertexCoords[i], 0);
        }

        gl.glEnd();

        if (texturingEnabled) {
            gl.glDisable(GL2.GL_TEXTURE_2D);
        }
    }

    private static void drawQuadsPolygonModel(GL2 gl,
                                              float[][] vertexCoords,
                                              float[][] normalCoords,
                                              float[][] textureCoords,
                                              Texture[] textures,
                                              int textureWrapSValue,
                                              int textureWrapTValue) {
        boolean texturingEnabled = false;
        boolean normalsEnabled = false;

        if (normalCoords != null) {
            normalsEnabled = true;
        }

        if (textureCoords != null) {
            texturingEnabled = true;

            gl.glEnable(GL2.GL_TEXTURE_2D);
        }

        for (int i = 0; i < vertexCoords.length; i++) {
            if (i % 4 == 0) {
                if (texturingEnabled) {
                    textures[i / 4].bind(gl);

                    gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S,
                            textureWrapSValue);
                    gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T,
                            textureWrapTValue);
                }

                gl.glBegin(GL2.GL_QUADS);
            }

            if (normalsEnabled) {
                gl.glNormal3fv(normalCoords[i], 0);
            }

            if (texturingEnabled) {
                gl.glTexCoord2fv(textureCoords[i], 0);
            }

            gl.glVertex3fv(vertexCoords[i], 0);

            if (i % 4 == 3) {
                gl.glEnd();
            }
        }

        if (texturingEnabled) {
            gl.glDisable(GL2.GL_TEXTURE_2D);
        }
    }

    public static void drawOBJModel(GL2 gl, OBJModel model, Texture texture) {
        if (texture != null) {
            gl.glEnable(GL2.GL_TEXTURE_2D);
            texture.bind(gl);

            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S,
                    GL2.GL_REPEAT);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T,
                    GL2.GL_REPEAT);
        }

        gl.glBegin(GL2.GL_TRIANGLES);

        for (int i = 0; i < model.getVertexIndices().size(); i++) {
            for (int j = 0; j < 3; j++) {
                if (!model.getNormalIndices().isEmpty()) {
                    gl.glNormal3fv(model.getNormals().get(model
                            .getNormalIndices().get(i)[j]), 0);
                }

                if (!model.getTextureIndices().isEmpty()) {
                    gl.glTexCoord2fv(model.getTextures().get(model
                            .getTextureIndices().get(i)[j]), 0);
                }

                gl.glVertex3fv(model.getVertices().get(model.getVertexIndices()
                        .get(i)[j]), 0);
            }
        }

        gl.glEnd();

        if (texture != null) {
            gl.glDisable(GL2.GL_TEXTURE_2D);
        }
    }

    public static void drawModelFromDisplaylist(GL2 gl,
                                                DisplayListStorable model) {
        displayDisplayList(gl, model);
    }

    public static void drawModelsFromDisplaylist(GL2 gl,
                                                 DisplayListStorable[] models) {
        displayDisplayLists(gl, models);
    }

//    public static void drawTest(GL2 gl, Texture[] textures)
//    {
//        gl.glEnable(GL2.GL_TEXTURE_2D);
//        
//        float edgeLength = 500.0f;
//        float doubleEdgeLength = 2*edgeLength;
//        
//        textures[2].bind(gl);
//        
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//
//        gl.glBegin(GL2.GL_QUADS);
//        //vpredu - textura vzadu
//        gl.glNormal3f(0, 0, 1);
//        gl.glTexCoord2f(0 ,1);
//        gl.glVertex3f(-edgeLength, doubleEdgeLength, edgeLength);
//        gl.glTexCoord2f(1 ,1);
//        gl.glVertex3f(edgeLength, doubleEdgeLength, edgeLength);
//        gl.glTexCoord2f(1 ,0);
//        gl.glVertex3f(edgeLength, 0.0f, edgeLength);
//        gl.glTexCoord2f(0 ,0);
//        gl.glVertex3f(-edgeLength, 0.0f, edgeLength);
//        gl.glEnd();
//        
//        textures[0].bind(gl);
//        
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//        
//        gl.glBegin(GL2.GL_QUADS);
//        //vzadu - textura vpredu
//        gl.glNormal3f(0,0,-1);
//        gl.glTexCoord2f(0, 0);
//        gl.glVertex3f(edgeLength, 0.0f, -edgeLength);
//        gl.glTexCoord2f(1, 0);
//        gl.glVertex3f(-edgeLength, 0.0f, -edgeLength);
//        gl.glTexCoord2f(1, 1);
//        gl.glVertex3f(-edgeLength, doubleEdgeLength, -edgeLength);
//        gl.glTexCoord2f(0, 1);
//        gl.glVertex3f(edgeLength, doubleEdgeLength, -edgeLength);
//        gl.glEnd();
//        
//        textures[3].bind(gl);
//        
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//        
//        gl.glBegin(GL2.GL_QUADS);
//        //vpravo
//        gl.glNormal3f(1, 0, 0);
//        gl.glTexCoord2f(0, 1);
//        gl.glVertex3f(edgeLength, doubleEdgeLength, edgeLength);
//        gl.glTexCoord2f(1, 1);
//        gl.glVertex3f(edgeLength, doubleEdgeLength, -edgeLength);
//        gl.glTexCoord2f(1, 0);
//        gl.glVertex3f(edgeLength, 0.0f, -edgeLength);
//        gl.glTexCoord2f(0, 0);
//        gl.glVertex3f(edgeLength, 0.0f, edgeLength);
//        gl.glEnd();
//        
//        textures[1].bind(gl);
//        
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//        
//        gl.glBegin(GL2.GL_QUADS);
//        //vlavo
//        gl.glNormal3f(-1,0,0);
//        gl.glTexCoord2f(1, 1);
//        gl.glVertex3f(-edgeLength, doubleEdgeLength, edgeLength);
//        gl.glTexCoord2f(0, 1);
//        gl.glVertex3f(-edgeLength, doubleEdgeLength, -edgeLength);
//        gl.glTexCoord2f(0, 0);
//        gl.glVertex3f(-edgeLength, 0.0f, -edgeLength);
//        gl.glTexCoord2f(1, 0);
//        gl.glVertex3f(-edgeLength, 0.0f, edgeLength);
//        gl.glEnd();
//        
//        textures[4].bind(gl);
//        
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//        
//        gl.glBegin(GL2.GL_QUADS);
//        //hore
//        gl.glNormal3f(0, 1, 0);
//        gl.glTexCoord2f(0, 1);
//        gl.glVertex3f(edgeLength, doubleEdgeLength, edgeLength);
//        gl.glTexCoord2f(0, 0);
//        gl.glVertex3f(edgeLength, doubleEdgeLength, -edgeLength);
//        gl.glTexCoord2f(1, 0);
//        gl.glVertex3f(-edgeLength, doubleEdgeLength, -edgeLength);
//        gl.glTexCoord2f(1, 1);
//        gl.glVertex3f(-edgeLength, doubleEdgeLength, edgeLength);
//        gl.glEnd();
//        
//        textures[5].bind(gl);
//        
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
//        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//        
//        gl.glBegin(GL2.GL_QUADS);
//        //dole
//        gl.glNormal3f(0,-1,0);
//        gl.glTexCoord2f(0, 0);
//        gl.glVertex3f(edgeLength, 0.0f, edgeLength);
//        gl.glTexCoord2f(1, 0);
//        gl.glVertex3f(-edgeLength, 0.0f, edgeLength);
//        gl.glTexCoord2f(1, 1);
//        gl.glVertex3f(-edgeLength, 0.0f, -edgeLength);
//        gl.glTexCoord2f(0, 1);
//        gl.glVertex3f(edgeLength, 0.0f, -edgeLength);
//        gl.glEnd();
//        
//        gl.glDisable(GL2.GL_TEXTURE_2D);
//    }
}
